#include "include/scheduable.h"
#include <stdint.h>
#include <QDebug>
#define resource_max 10  //最大共享资源类型需求数目
#include "include/simul.h"
#include "include/priority.h"
#include "include/resource.h"
int H_i_r_output(Task *analysed_task,uint32_t r)                               //support virable for Ir
{
    uint32_t Hir=0;
    while(Hir<H_i_r(analysed_task,r,Hir))
        Hir=H_i_r(analysed_task,r,Hir);
    return Hir;
}

int H_i_r(Task *analysed_task,uint32_t r,uint32_t last_Hir)
{
  uint32_t sum_H=0;
  uint32_t Llq_max=0;
    for(int h=0;h<get_tasknum();h++)
       if(taskSets[h].task_priority>analysed_task->task_priority)
           for(int r=0;r<RESOURCE_MAX;r++)
               for(int q=0;q<RESOURCE_MAX;q++)
                   if(analysed_task->resource_on_core[r]==taskSets[h].resource_on_core[q])
                      sum_H+=ceiling(last_Hir+taskSets[h].task_wcrt,taskSets[h].task_period)
                              *taskSets[h].resource_duration[q];
    sum_H+=analysed_task->resource_duration[r];
    for(int l=0;l<get_tasknum();l++)
        for(int q=0;q<RESOURCE_MAX;q++)
            if(taskSets[l].task_priority<analysed_task->task_priority&&
                    taskSets[l].resource_on_core[q]==analysed_task->resource_on_core[r])
                if(Llq_max<taskSets[l].resource_duration[q])
                    Llq_max=taskSets[l].resource_duration[q];
    sum_H+=Llq_max;
    return sum_H;
}


int ceiling(uint32_t a,uint32_t b)
{

    return  (a + b -1) / b ;
}


int local_resource_blocking_analyse(Task tasksets[],Task *analysed_task)   //bi
{
    uint32_t L_max=0;
    for(int i=0;i<get_tasknum();i++)
        for(int j=0;j<resource_max;j++)
            if(analysed_task->resource_duration[j]!=0)
             if(
                     analysed_task->task_priority>tasksets[i].task_priority&&
                     analysed_task->on_core==tasksets[i].on_core&&
                     L_max<tasksets[i].resource_duration[j]&&
                    // resource[analysed_task->resource_type[j]-1].ceiling_prior<analysed_task->task_priority&&
                     !resource[analysed_task->resource_type[j]-1].is_global
                     )
              L_max=(uint32_t)tasksets[i].resource_duration[j];
    uint32_t access_times=1;
      for(int j=0;j<resource_max;j++)
          if(analysed_task->resource_duration[j]!=0)
          if(resource[analysed_task->resource_type[j]-1].is_global&&analysed_task->resource_duration[j]!=0)
          access_times+=1;
      return access_times*L_max;

}
int non_critical_area_delay_analyse(Task tasksets[],Task *analysed_task,uint32_t t)                    //Ic(t)
{
   uint32_t delta_i_h;
   uint32_t sum=0;

   for(int h=0;h<get_tasknum();h++)
       if(tasksets[h].task_priority>analysed_task->task_priority&&tasksets[h].on_core==analysed_task->on_core)
       {
       delta_i_h=tasksets[h].task_wcet;
       for(int q=0;q<resource_max;q++)
          {
            for(int temp=0;temp<resource_max;temp++)
            {
               if(tasksets[h].resource_type[q]==analysed_task->resource_type[temp]&&tasksets[h].resource_isglobal[q])
                  delta_i_h-=tasksets[h].resource_duration[q];//任务h,q与i所需资源是否有同一种
            }
           }
       sum+=delta_i_h*ceiling(t+tasksets[h].task_wcrt- delta_i_h,tasksets[h].task_period);
       }
   return sum;
}


int global_resource_critical_area_delay_analyse(Task tasksets[],Task *analysed_task,uint32_t t)   //Ir(t)
{
    uint32_t total_delay=0,core_delay=0;
    for(int k=0;k<M;k++)
    {
        if(analysed_task->on_core==k)
        {
            for(int x=0;x<get_tasknum();x++)
              if(taskSets[x].task_id!=analysed_task->task_id)
               for(int r=0;r<RESOURCE_MAX;r++)
                   if(taskSets[x].resource_duration[r]!=0)
                 if(taskSets[x].resource_on_core[r]==(uint32_t)k&&taskSets[x].task_period!=0&&resource[taskSets[x].resource_type[r]-1].is_global)
                   core_delay+=(ceiling(t+taskSets[x].task_wcrt-taskSets[x].resource_duration[r],taskSets[x].task_period)*taskSets[x].resource_duration[r]);
        }
        else
        {
            for(int r=0;r<RESOURCE_MAX;r++)
                if(analysed_task->resource_on_core[r]==(uint32_t)k&&analysed_task->on_core!=k)
                  {
                    uint32_t sum_1=0,sum_2=0;
                    for(int r=0;r<RESOURCE_MAX;r++)
                        if(analysed_task->resource_duration[r]!=0)
                    if(analysed_task->resource_on_core[r]==(uint32_t)k&&resource[analysed_task->resource_type[r]-1].is_global)
                       sum_1+=H_i_r_output(analysed_task,r);
                    for(int r=0;r<RESOURCE_MAX;r++)
                        if(analysed_task->resource_duration[r]!=0)
                    if(analysed_task->resource_on_core[r]==(uint32_t)k&&resource[analysed_task->resource_type[r]-1].is_global)
                       {
                        sum_2+= analysed_task->resource_duration[r] ;
                        for(int x=0;x<get_tasknum();x++)
                            if(taskSets[x].task_id!=analysed_task->task_id)
                                for(int temp=0;temp<RESOURCE_MAX;temp++)
                                    if(taskSets[x].resource_type[temp]==analysed_task->resource_type[r])
                                        sum_2+=ceiling(taskSets[x].task_wcrt+t,taskSets[x].task_period)*taskSets[x].resource_duration[temp];
                        }

                           sum_2+=table_tasks_delay_analyse(analysed_task,t);
                    if(sum_1>sum_2)
                        core_delay=sum_2;
                    else
                        core_delay=sum_1;

                  }
        }
        total_delay+=core_delay;

    }
    return total_delay;

}


int table_tasks_delay_analyse(Task *analysed_task,uint32_t t)
{
    int temp=0;
    for(int i=0;i<get_tasknum();i++)
    {if(taskSets[i].task_type==0&&(int)taskSets[i].partition.part_on_core[0]==analysed_task->on_core)
    {temp=i;break;}}
       int max_delay=0;
       int sum_length=0;
       for(int j=0;j<taskSets[temp].num_subsection;j++)
       {
           sum_length+=taskSets[temp].partition.part_length[j] ;
       }
       for(int j=0;j<taskSets[temp].num_subsection;j++)
       {
              int temp_delay=0;
              temp_delay=(taskSets[temp].partition.start[j]+t)/lcm*sum_length;
              for(int i=0;i<taskSets[temp].num_subsection;i++)
              if(taskSets[temp].partition.start[i]<(taskSets[temp].partition.start[j]+t)%lcm)
              {temp_delay+=taskSets[temp].partition.part_length[i]; }
              for(int i=0;i<j;i++)
              {temp_delay-=taskSets[temp].partition.part_length[i];}
              if(max_delay<temp_delay)
                  max_delay=temp_delay;
       }
       return max_delay;
}

int access_control_delay_analyse(Core core)    //x
{
    int temp_window=0;
    int max_window=0;
    for(int j=0;j<core.table_length;j++)
    {
        temp_window+= core.table[j].end-core.table[j].start;
        if(core.table[j].end!=core.table[j+1].start)
           if(max_window<temp_window)
             {
               max_window=temp_window;
               temp_window=0;
             }
    }
    return max_window+2;
}

bool schedulable_analyse(Task tasksets[],Task *analysed_task)
{
    int t=analysed_task->task_wcet;
    int b=local_resource_blocking_analyse(tasksets,analysed_task);
    int I_C=non_critical_area_delay_analyse(tasksets,analysed_task,t);
    int I_R=global_resource_critical_area_delay_analyse(tasksets,analysed_task,t);
    int I_T=table_tasks_delay_analyse(analysed_task,t);
    int x=access_control_delay_analyse(cores[analysed_task->on_core]);
    while(t<analysed_task->task_wcet+b+I_C+I_R+I_T+x)
     {
        t=analysed_task->task_wcet+b+I_C+I_R+I_T+x;
        if(t>analysed_task->task_deadline)
         {
          qDebug()<<"拒绝任务"<<analysed_task->task_id<<"当前最坏相应时间"<<t<<"截止时间"<<analysed_task->task_deadline;
          qDebug()<<"b="<<b<<"Ic="<<I_C<<"Ir="<<I_R<<"It="<<I_T<<"x="<<x;
         return false;
        }
        b=local_resource_blocking_analyse(tasksets,analysed_task);
        I_C=non_critical_area_delay_analyse(tasksets,analysed_task,t);
        I_R=global_resource_critical_area_delay_analyse(tasksets,analysed_task,t);
        I_T=table_tasks_delay_analyse(analysed_task,t);
        x=access_control_delay_analyse(cores[analysed_task->on_core]);
     }
      analysed_task->task_wcrt=t;
      qDebug()<<"接受任务"<<analysed_task->task_id<<"当前最坏相应时间"<<t<<"截止时间"<<analysed_task->task_deadline;
      qDebug()<<"b="<<b<<"Ic="<<I_C<<"Ir="<<I_R<<"It="<<I_T<<"x="<<x;
        return true;

}
